package com.gml.jdk.proxy.dynamic;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;

/**
 * @ClassName : $Proxy11
 * @Description : 代理类反编译后代码
 * @Author : gml
 * @Date: 2020-10-20 17:31
 */
public final class $Proxy11 extends Proxy implements IHello {
    private static Method m1;
    private static Method m2;
    private static Method m3;
    private static Method m0;

    /**
     *注意这里是生成代理类的构造方法，方法参数为InvocationHandler类型，看到这，是不是就有点明白
     *super(paramInvocationHandler)，是调用父类Proxy的构造方法。
     *父类持有：protected InvocationHandler h;
     *Proxy构造方法：
     *    protected Proxy(InvocationHandler h) {
     *         Objects.requireNonNull(h);
     *         this.h = h;
     *     }
     *
     */
    public $Proxy11(InvocationHandler var1)   {
        super(var1);
    }

    public final boolean equals(Object var1)   {
        try {
            return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final String toString()   {
        try {
            return (String)super.h.invoke(this, m2, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    /**
     * DynaicTest.invoke(Object proxy, Method method, Object[] args) 方法会代理被代理对象的所有方法，因此有可能造成死循环
     * 由此可知死循环调用路径为：DynaicTest.main内DynaicTest.sayHello()
     * （Hello即动态生成的$Proxy11类实例）-->$Proxy11.invoke方法内this.h.invoke(this, m3, new Object[] { paramInvocation })
     *  -->DynaicTest.invoke方法内paramMethod.invoke(paramObject, paramArrayOfObject)
     *  -->$Proxy11.invoke方法内this.h.invoke(this, m3, new Object[] { paramInvocation })
     *  -->DynaicTest.invoke方法内paramMethod.invoke(paramObject, paramArrayOfObject) -->....
     *
     *  解决：传入被代理类的实例，避免死循环
     */
    public final void sysHello()   {

        try {
            super.h.invoke(this, m3, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final int hashCode()   {
        try {
            return (Integer)super.h.invoke(this, m0, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m3 = Class.forName("com.gml.test.proxy.dynamic.IHello").getMethod("sysHello");
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}

